
#include "gd32f3x0.h"
#include "bsp_usart.h"

//有些东东得收起来,不然会被盗调
volatile uint32_t num = 1;

/*******************USART编程要点*********************************************/
//使能RX和TX引脚GPIO时钟和USART时钟     		开时钟
//初始化GPIO，并将GPIO复用到USART上
//配置USART参数
//配置中断控制器并使能中断
//使能USART
//在USART中断服务函数中写相应的功能

//嵌套向量中断控制器初始化函数
static void NVIC_Configuration(void) //静态函数仅供本文件调用
{
    nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
    nvic_irq_enable(DEBUG_USART_IRQ,2,0);  //WIFI最大,RTC次之(不TIMER2次之)
}

//USART初始化函数(使用USART点灯的过程中不用中断)
void DEBUG_USART_Config(void)
{
    /* enable COM GPIO clock */
    rcu_periph_clock_enable(DEBUG_USART_RX_GPIO_CLK);  //DEBUG_USART位于PA9 PA10
    /* enable USART clock */
    rcu_periph_clock_enable(DEBUG_USART_CLK);
    /* connect port to USARTx_Tx */
    gpio_af_set(DEBUG_USART_TX_GPIO_PORT, DEBUG_USART_TX_AF,DEBUG_USART_TX_PIN);

    /* connect port to USARTx_Rx */
    gpio_af_set(DEBUG_USART_RX_GPIO_PORT, DEBUG_USART_RX_AF,DEBUG_USART_RX_PIN);

    /* configure USART Tx as alternate function push-pull */
    gpio_mode_set(DEBUG_USART_TX_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP,DEBUG_USART_TX_PIN);
    gpio_output_options_set(DEBUG_USART_TX_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ,DEBUG_USART_TX_PIN);

    /* configure USART Rx as alternate function push-pull */
    gpio_mode_set(DEBUG_USART_RX_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, DEBUG_USART_RX_PIN);
    gpio_output_options_set(DEBUG_USART_RX_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ,DEBUG_USART_RX_PIN);

    /* USART configure */
    usart_deinit(DEBUG_USART);
    usart_baudrate_set(DEBUG_USART, DEBUG_USART_BAUDRATE);
    usart_receive_config(DEBUG_USART, USART_RECEIVE_ENABLE);
    usart_transmit_config(DEBUG_USART, USART_TRANSMIT_ENABLE);
    NVIC_Configuration();
    usart_interrupt_enable(DEBUG_USART, USART_INT_IDLE);
    usart_interrupt_flag_clear(DEBUG_USART,USART_INT_FLAG_IDLE);
    usart_interrupt_enable(DEBUG_USART, USART_INT_RBNE);
    usart_interrupt_flag_clear(DEBUG_USART, USART_INT_FLAG_RBNE);
    usart_enable(DEBUG_USART);
}

//发送一个字符
void DEBUG_USART_SendByte(uint8_t ch)
{
    usart_data_transmit(DEBUG_USART, (uint8_t)ch);
    //下面就是等待发送完成       //TXE发送寄存器为空(但移位寄存器可能并不为空)，发送单个字节的时候使用
    while (usart_flag_get(DEBUG_USART, USART_FLAG_TBE)== RESET)
    {
        ;
    }
}

//下面得重写一些标准的C库函数(需要重写前面包含stdio.h吗)

//重定向c库函数printf到串口，重定向后可使用printf函数
int fputc(int ch, FILE *f) //这里的FILE *f其实没什么屌用
{
    DEBUG_USART_SendByte((uint8_t)ch);
    return ch; //按标准返回
}

//重定向c库函数scanf到串口,重定向后可使用scanf,getchar等函数
int fgetc(FILE *f)
{ //这里是不用中断的
    while (usart_flag_get(DEBUG_USART, USART_FLAG_RBNE)== RESET)
    {
        ;  //说明scanf函数会一直等
    }
    return usart_data_receive(DEBUG_USART);
}

#define RX_NUM 64
void DEBUG_USART_IRQHandler(void)
{
    static char RxBuffer[RX_NUM];
    static uint8_t i = 0;

    //如果是接受中断  (一般发送不需要中断,连续发送)
    if (usart_interrupt_flag_get(DEBUG_USART,USART_INT_FLAG_RBNE) == SET) //如果是接受产生的中断
    {
        usart_interrupt_flag_clear(DEBUG_USART, USART_INT_FLAG_RBNE);
        RxBuffer[i++] =usart_data_receive(DEBUG_USART); //接收到后马上返回去  (相应的中断标志会被清除，在读出数据后)
    }
    //如果是接受中断  (一般发送不需要中断,连续发送)
    if (usart_interrupt_flag_get(DEBUG_USART,USART_INT_FLAG_IDLE) == SET) //如果是接受产生的中断
    {
        usart_interrupt_flag_clear(DEBUG_USART,USART_INT_FLAG_IDLE);
        usart_data_receive(DEBUG_USART); //这里是为了防止反复进入空闲中断(只进入一次)
        if (i > 0)
        {
            RxBuffer[i] = '\0';
            i = 0;
            num = atoi((const char *)RxBuffer); //字符串转数值
            //printf("num: %d\r\n", num);
        }
    }
}
